package com.autumn.util.data;

import java.util.ArrayList;
import java.util.List;

import com.autumn.common.api.application.dto.input.IPageQueryInput;
import com.autumn.common.api.application.dto.input.PageQueryInput;
import com.autumn.common.api.application.dto.output.PageQueryResult;
import com.autumn.mybatis.criterion.IQuerySection;
import com.autumn.util.AutoMapUtils;
import com.autumn.util.ExceptionUtils;
import com.autumn.util.NumberUtils;
import com.autumn.util.function.FunctionOneResult;
import com.autumn.util.function.FunctionTwoAction;

/**
 * 页查询抽象
 * 
 * @author 老码农
 *
 *         2018-04-11 10:26:40
 */
public abstract class AbstractPageQueryBuilder<TQueryBuilder extends AbstractPageQueryBuilder<TQueryBuilder>>
		extends AbstractQueryBuilder<TQueryBuilder> {

	private IPageQueryInput input = null;

	/**
	 * 
	 */
	public AbstractPageQueryBuilder() {

	}

	/**
	 * 页
	 * 
	 * @param input
	 *            输入
	 * @param maxPageSize
	 *            最大页大小
	 * @return
	 */
	public TQueryBuilder page(IPageQueryInput input, int maxPageSize) {
		if (input == null) {
			input = new PageQueryInput();
		}
		if (input.getCurrentPage() < NumberUtils.NUM_INT_1) {
			input.setCurrentPage(NumberUtils.NUM_INT_1);
		}
		if (input.getPageSize() < NumberUtils.NUM_INT_1) {
			input.setPageSize(NumberUtils.NUM_INT_1);
		}
		if (maxPageSize > NumberUtils.NUM_INT_ZERO) {
			if (input.getPageSize() > maxPageSize) {
				input.setPageSize(maxPageSize);
			}
		}
		this.criteriaByItem(input.getCriterias());
		this.input = input;
		return this.returnThis();
	}

	/**
	 * 页
	 * 
	 * @param input
	 *            输入
	 * @return
	 */
	public TQueryBuilder page(IPageQueryInput input) {
		return this.page(input, -1);
	}

	/**
	 * 页
	 * 
	 * @param currentPage
	 *            当前页
	 * @param pageSize
	 *            页大小
	 * @return
	 */
	public TQueryBuilder page(int currentPage, int pageSize) {
		if (this.input == null) {
			this.input = new PageQueryInput();
		}
		if (currentPage < NumberUtils.NUM_INT_1) {
			currentPage = NumberUtils.NUM_INT_1;
		}
		if (pageSize < NumberUtils.NUM_INT_1) {
			pageSize = NumberUtils.NUM_INT_1;
		}
		this.input.setCurrentPage(currentPage);
		this.input.setPageSize(pageSize);
		return this.returnThis();
	}

	/**
	 * 重置,清除所有条件
	 * 
	 * @return
	 */
	@Override
	public TQueryBuilder reset() {
		super.reset();
		this.input = null;
		return this.returnThis();
	}

	/**
	 * 记录数量
	 * 
	 * @param countDelegate
	 *            统计委托
	 * @return
	 *
	 */
	protected int toCount(FunctionOneResult<IQuerySection, Integer> countDelegate) {
		if (this.getQuery().getOrderColumns() == 0) {
			ExceptionUtils.throwValidationException("无排序列,无法分页。");
		}
		if (this.input == null) {
			ExceptionUtils.throwValidationException("未设置页信息。");
		}
		IQuerySection section = this.getQuery().builderSection();
		return countDelegate.apply(section);
	}

	/**
	 * 输出结果
	 * 
	 * @param countDelegate
	 *            统计委托
	 * @param queryDelegate
	 *            查询委托
	 * @return
	 *
	 */
	protected <TResult> PageQueryResult<TResult> toPageResult(FunctionOneResult<IQuerySection, Integer> countDelegate,
			FunctionOneResult<IQuerySection, List<TResult>> queryDelegate) {
		int count = toCount(countDelegate);
		PageQueryResult<TResult> page = new PageQueryResult<TResult>(this.input.getCurrentPage(),
				this.input.getPageSize(), count);
		this.getQuery().page(page.getCurrentPage(), page.getPageSize());
		IQuerySection section = this.getQuery().builderSection();
		if (count > 0) {
			List<TResult> entitys = queryDelegate.apply(section);
			page.setItems(entitys);
		} else {
			page.setItems(new ArrayList<>());
		}
		return page;
	}

	/**
	 * 输出结果
	 * 
	 * @param countDelegate
	 *            统计委托
	 * @param queryDelegate
	 *            查询委托
	 * @param resultClass
	 *            结果类型
	 * @return
	 *
	 */
	protected <TEntity, TResult> PageQueryResult<TResult> toPageResult(
			FunctionOneResult<IQuerySection, Integer> countDelegate,
			FunctionOneResult<IQuerySection, List<TEntity>> queryDelegate, Class<TResult> resultClass) {
		return this.toPageResult(countDelegate, queryDelegate, resultClass, null);
	}

	/**
	 * 输出结果
	 * 
	 * @param countDelegate
	 *            统计委托
	 * @param queryDelegate
	 *            查询委托
	 * @param resultClass
	 *            结果类型
	 * @param convertDelegate
	 *            转换委托
	 * @return
	 *
	 */
	protected <TEntity, TResult> PageQueryResult<TResult> toPageResult(
			FunctionOneResult<IQuerySection, Integer> countDelegate,
			FunctionOneResult<IQuerySection, List<TEntity>> queryDelegate, Class<TResult> resultClass,
			FunctionTwoAction<TEntity, TResult> convertDelegate) {
		int count = toCount(countDelegate);
		PageQueryResult<TResult> page = new PageQueryResult<TResult>(this.input.getCurrentPage(),
				this.input.getPageSize(), count);
		this.getQuery().page(page.getCurrentPage(), page.getPageSize());
		IQuerySection section = this.getQuery().builderSection();
		if (count > 0) {
			List<TEntity> entitys = queryDelegate.apply(section);
			List<TResult> items = AutoMapUtils.mapList(entitys, resultClass, convertDelegate);
			page.setItems(items);
		} else {
			page.setItems(new ArrayList<>());
		}
		return page;
	}
}
